package com.zhongkun.datahome.service.service.impl;

import com.zhongkun.datahome.common.constant.Constants;
import com.zhongkun.datahome.common.core.domain.entity.SysUser;
import com.zhongkun.datahome.common.core.domain.entity.TenantUser;
import com.zhongkun.datahome.common.core.domain.model.LoginUser;
import com.zhongkun.datahome.common.exception.ServiceException;
import com.zhongkun.datahome.common.utils.DateUtils;
import com.zhongkun.datahome.common.utils.MessageUtils;
import com.zhongkun.datahome.common.utils.SecurityUtils;
import com.zhongkun.datahome.common.utils.ip.IpUtils;
import com.zhongkun.datahome.core.mapper.SysUserMapper;
import com.zhongkun.datahome.core.repository.TenantUserRepository;
import com.zhongkun.datahome.core.service.ISysUserService;
import com.zhongkun.datahome.core.service.ITenantUserService;
import com.zhongkun.datahome.framework.manager.AsyncManager;
import com.zhongkun.datahome.framework.manager.factory.AsyncFactory;
import com.zhongkun.datahome.framework.security.context.AuthenticationContextHolder;
import com.zhongkun.datahome.framework.security.context.WechatAuthenticationToken;
import com.zhongkun.datahome.framework.web.service.TokenService;
import com.zhongkun.datahome.service.constant.YesOrNoEnum;
import com.zhongkun.datahome.service.domain.CustomerBase;
import com.zhongkun.datahome.service.domain.CustomerFamily;
import com.zhongkun.datahome.service.repository.CustomerBaseRepository;
import com.zhongkun.datahome.service.repository.CustomerFamilyRepository;
import com.zhongkun.datahome.service.req.cmd.customer.AppletsPhoneNumberCmd;
import com.zhongkun.datahome.service.req.cmd.customer.CustomerBaseCmd;
import com.zhongkun.datahome.service.service.ICustomerBaseService;
import com.zhongkun.datahome.service.service.IWeixinService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * 客户基础Service业务层处理
 *
 * @author ruoyi
 * @date 2025-04-14
 */
@Service
public class CustomerBaseServiceImpl implements ICustomerBaseService {
    @Resource
    private CustomerFamilyRepository customerFamilyRepository;

    @Resource
    private CustomerBaseRepository customerBaseRepository;

    @Resource
    private TenantUserRepository tenantUserRepository;

    @Resource
    private IWeixinService weixinService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private AuthenticationManager weixinAuthenticationManager;

    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    @Transactional
    public CustomerBase save(CustomerBaseCmd cmd) {
        // 校验
        CustomerBase byMobile = customerBaseRepository.getByMobile(cmd.getMobile());
        if (Objects.nonNull(byMobile)) {
            byMobile.setCustomerName(cmd.getCustomerName());
            customerBaseRepository.updateById(byMobile);

            // 同步修改系统用户
            SysUser user = sysUserMapper.selectUserByUserName(cmd.getMobile(), null);
            if (!Objects.equals(user.getNickName(), cmd.getCustomerName())) {
                user.setNickName(cmd.getCustomerName());
                sysUserMapper.updateUser(user);
            }
            return byMobile;
        }

        // 创建客户
        Long tenantUserId = tenantUserRepository.createTenantUser(cmd.getMobile(), cmd.getCustomerName());
        CustomerBase customerBase = CustomerBase.of(cmd);
        customerBase.setTenantUserId(tenantUserId);
        customerBaseRepository.save(customerBase);

        // 创建家庭
        CustomerFamily family = CustomerFamily.of(cmd.getCustomerName() + "家庭", customerBase.getId());
        customerFamilyRepository.save(family);

        // 设为户主
        customerBase.setFamilyId(family.getId());
        customerBase.setIsOwner(YesOrNoEnum.YES.getCode());
        customerBase.setRelation("户主");
        customerBaseRepository.updateById(customerBase);

        return customerBase;
    }

    @Override
    public String login(AppletsPhoneNumberCmd cmd) {
        SecurityUtils.setTenantId(cmd.getTenantId());
        String phoneNumber = weixinService.getPhoneNumber(cmd.getAppId(), cmd.getLoginCode());
        if (Objects.isNull(phoneNumber)) {
            throw new ServiceException("获取手机号失败");
        }

        return loginByMobile(phoneNumber);
    }

    @Override
    public void removeByFamilyId(Long familyId) {
        List<CustomerBase> customerBaseList = customerBaseRepository.getMemberByFamilyId(familyId);

        for (CustomerBase customerBase : customerBaseList) {
            customerBaseRepository.removeById(customerBase.getId());
            Long tenantUserId = customerBase.getTenantUserId();

            TenantUser tenantUser = tenantUserRepository.getById(tenantUserId);
            userService.deleteTokenUserById(tenantUser.getUserId());

            SysUser sysUser = userService.selectUserById(tenantUser.getUserId());
            if (Objects.nonNull(sysUser) && CollectionUtils.isEmpty(sysUser.getRoles())) {
                userService.deleteUserById(sysUser.getUserId());
            }
        }
    }

    @Override
    public String loginByMobile(String mobile) {
        Authentication authentication = new WechatAuthenticationToken(mobile);
        AuthenticationContextHolder.setContext(authentication);
        // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
        authentication = weixinAuthenticationManager.authenticate(authentication);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        SecurityUtils.tenantIdRemove();

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(mobile, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(loginUser);
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }

}
